#pragma once
#include <iostream>
#include <pthread.h>
#include <vector>
#include "Sem.hpp"
#include "Cond.hpp"
#include "Mutex.hpp"
using namespace SemModule;
using namespace SemModule;
using namespace CondModule;
using namespace MutexData;

namespace RingBufferModule
{
	template <typename T>
	class RingBuffer
	{
	public:
		RingBuffer(int cap) : _ring(cap), _cap(cap), _p_step(0), _c_step(0), _datasem(0), _spacesem(cap)
		{
		}
		// 生产
		void Equeue(const T &in)
		{
			_spacesem.P();
			{
				LockGuard lockguard(_p_lock);
				_ring[_p_step] = in;
				_p_step++;
				_p_step %= _cap; // 保持环状
			}
			
			_datasem.V();
		}
		// 消费
		void Pop(T *out)
		{
			_datasem.P();
			{
				LockGuard lockguard(_c_lock);
				*out = _ring[_c_step];
				_c_step++;
				_c_step %= _cap;
			}
			
			_spacesem.V();
		}
		~RingBuffer()
		{
		}

	private:
		std::vector<T> _ring; // 环， 临界资源
		int _cap;			  // 总容量
		int _p_step;		  // 生产者位置
		int _c_step;		  // 消费位置

		Sem _datasem;  // 数据信号量
		Sem _spacesem; // 空间信号量

		Mutex _p_lock; // 生产者锁
        Mutex _c_lock; // 消费者锁
	};
}